local Msg = require("core.Msg")
local Lang = require("common.Lang")
local ExcelMap = require("excel.Map")
local Map = require("core.Map")
local Status = require("scene.Status")
local ObjHuman = require("core.ObjHuman")
local RoleAttr = require("role.RoleAttr")
local ArmourExcel = require("excel.Armour")
local ArmourBaseConfig = ArmourExcel.armour
local ArmourLogicFL = require("armour.ArmourLogicFL")
local ArmourDefine = require("armour.Define")
local Util = require("common.Util")
local Obj = require("core.Obj")
local Grid = require("bag.Grid")
local ItemDefine = require("bag.ItemDefine")
local BagLogic = require("bag.BagLogic")

local function get_grid(itemID, itemNum, itemColor, itemBind)
    local grid = Grid.create(nil, itemID, itemNum, itemBind, ItemDefine.qualityOut[itemColor])
    return grid
end

function CG_ARMOUR_OPEN(human, msg)
    local nAllAttr = ArmourLogicFL.calcAllAttr(human)
    sendArmourAllAttr(human, nAllAttr)
end

function CG_ARMOUR_QUERY(human, msg)
    local nArmourID = msg.id
    local nSendMsg = Msg.gc.GC_ARMOUR_QUERY
    nSendMsg.curid = human.db.curarmourid or 0
    nSendMsg.armourlist[0] = 0
    if nArmourID == 0 then
        for k, v in pairs(ArmourBaseConfig) do
            nSendMsg.armourlist[0] = nSendMsg.armourlist[0] + 1
            local nArmourData = nSendMsg.armourlist[nSendMsg.armourlist[0]]
            warpArmourData(nArmourData, k, human)
        end
    else
        if not ArmourBaseConfig[nArmourID] then
            return
        end

        nSendMsg.armourlist[0] = nSendMsg.armourlist[0] + 1
        local nArmourData = nSendMsg.armourlist[nSendMsg.armourlist[0]]
        warpArmourData(nArmourData, nArmourID, human)
    end
    Msg.send(nSendMsg, human.fd)
end

function CG_ARMOUR_HOLD(human, msg)
    local nArmourID = msg.id
    local nActionType = msg.type
    if nActionType ~= 0 and nActionType ~= 1 then
        return
    end
    local nArmourDBData = ArmourLogicFL.getArmourDBData(nArmourID, human)
    if not nArmourDBData then
        return
    end
    if nArmourDBData.state == nActionType then
        return
    end
    nArmourDBData.state = nActionType
    if nArmourDBData.state == ArmourDefine.ARMOUR_STATETYPE_HOLD then
        human.db.curarmourid = nArmourID
    else
        human.db.curarmourid = 0
    end
    Status.sendViewStatus(human, true)
    local nSendMsg = Msg.gc.GC_ARMOUR_HOLD
    nSendMsg.result = 0
    nSendMsg.id = nArmourID
    Msg.send(nSendMsg, human.fd)
end

function CG_ARMOUR_ACTIVE(human, msg, fromItemActive)
    local nArmourID = msg.id
    if not ArmourLogicFL.armourValid(nArmourID) then
        return
    end

    local msgErr = Msg.gc.GC_BROADCAST
    msgErr.type = Lang.MOUSE
    if ArmourLogicFL.getArmourDBData(nArmourID, human) then
        msgErr.msg = "已激活此战甲"
        Msg.send(msgErr, human.fd)
        return
    end

    if not fromItemActive then
        local nNeedItemList = ArmourBaseConfig[nArmourID].activeItem
        local nEnoughtItem = true
        for k, v in ipairs(nNeedItemList) do
            if BagLogic.getItemCount(human, v[1]) < v[2] then
                nEnoughtItem = false
                msgErr.msg = "道具不足"
                Msg.send(msgErr, human.fd)
                break
            end
        end

        if nEnoughtItem == true then
            for k, v in ipairs(nNeedItemList) do
                BagLogic.delItemsById(human, v[1], v[2], "armouractive")
            end

            local result = ArmourLogicFL.armourActive(human, nArmourID)
            if result then
                local nSendMsg = Msg.gc.GC_ARMOUR_ACTIVE
                nSendMsg.result = 0
                nSendMsg.id = nArmourID
                Msg.send(nSendMsg, human.fd)
            end
        end
    else
        local result = ArmourLogicFL.armourActive(human, nArmourID)
        if result then
            local nSendMsg = Msg.gc.GC_ARMOUR_ACTIVE
            nSendMsg.result = 0
            nSendMsg.id = nArmourID
            Msg.send(nSendMsg, human.fd)
        end
    end
end

function CG_ARMOUR_UPDATE(human, msg, fromItemLv)
    local nArmourID = msg.id
    if not ArmourLogicFL.armourValid(nArmourID) then
        return
    end

    local nArmourLvUpConfig = ArmourLogicFL.getLvUpConfig(nArmourID)
    if not nArmourLvUpConfig then
        return false
    end

    local msgErr = Msg.gc.GC_BROADCAST
    msgErr.type = Lang.MOUSE
    local nArmourDBData = ArmourLogicFL.getArmourDBData(nArmourID, human)
    if not  nArmourDBData then
        msgErr.msg = "暂未激活此战甲"
        Msg.send(msgErr, human.fd)
        return
    end

    local nArmourLvConfig = nArmourLvUpConfig[nArmourDBData.lv]
    if not nArmourLvConfig then
        return
    end

    local nArmourNextLvConfig = nArmourLvUpConfig[nArmourDBData.lv + (fromItemLv or 1)]
    if not nArmourNextLvConfig then
        msgErr.msg = "超出最大等级"
        Msg.send(msgErr, human.fd)
        return
    end

    if nArmourDBData.lv >= human.db.lv then
        msgErr.msg = "战甲等级不能超过人物等级"
        Msg.send(msgErr, human.fd)
        return
    end

    if not fromItemLv then
        local nNeedItemList = nArmourLvConfig.updateItem
        local nNeedMoney = nArmourLvConfig.updateMoney
        local nEnoughtItem = true
        if ObjHuman.getYinliang(human) < nNeedMoney then
            msgErr.msg = "银两不足"
            Msg.send(msgErr, human.fd)
            return
        end

        for k, v in ipairs(nNeedItemList) do
            if BagLogic.getItemCount(human, v[1]) < v[2] then
                nEnoughtItem = false
                msgErr.msg = "道具不足"
                Msg.send(msgErr, human.fd)
                break
            end
        end

        if nEnoughtItem == true then
            ObjHuman.decYinliang(human, nNeedMoney, "armourupdate")
            for k, v in ipairs(nNeedItemList) do
                BagLogic.delItemsById(human, v[1], v[2], "armourupdate")
            end

            local result = ArmourLogicFL.armourLvUp(human, nArmourID, 1, nArmourDBData)
            if result then
                return true
            end
        end
    else
        local result = ArmourLogicFL.armourLvUp(human, nArmourID, fromItemLv, nArmourDBData)
        if result then
            return true
        end
    end
    return false
end

function CG_ARMOUR_STARUP(human, msg, fromItemStar)
    local nArmourID = msg.id
    if not ArmourLogicFL.armourValid(nArmourID) then
        return
    end

    local nArmourBaseConfig = ArmourBaseConfig[nArmourID]
    local msgErr = Msg.gc.GC_BROADCAST
    msgErr.type = Lang.MOUSE
    local nArmourDBData = ArmourLogicFL.getArmourDBData(nArmourID, human)
    if not  nArmourDBData then
        msgErr.msg = "暂未激活此战甲"
        Msg.send(msgErr, human.fd)
        return
    end

    local nStar = nArmourDBData.star
    if not fromItemStar then
        local nNeedItemID = nArmourBaseConfig.starItem
        if nStar < #nArmourBaseConfig.starupdata then               -- 升星
            local nStarConfigData = nArmourBaseConfig.starupdata[nStar + 1]
            if nStarConfigData then
                local nNeedMoney = nStarConfigData[2]
                local nEnoughtItem = true
                if ObjHuman.getYinliang(human) < nNeedMoney then
                    nEnoughtItem = false
                    msgErr.msg = "银两不足"
                    Msg.send(msgErr, human.fd)
                end

                if BagLogic.getItemCount(human, nNeedItemID) < nStarConfigData[1] then
                    nEnoughtItem = false
                    msgErr.msg = "道具不足"
                    Msg.send(msgErr, human.fd)
                end

                if nEnoughtItem == true then
                    ObjHuman.decYinliang(human, nNeedMoney, "armourstarupdate")
                    BagLogic.delItemsById(human, nNeedItemID, nStarConfigData[1], "armourstarupdate")

                    local result = ArmourLogicFL.armourStarUp(human, nArmourID, 1, nArmourDBData)
                    if result then
                        return true
                    end
                end

            end
        else                                                        -- 培养
            local nFeedCount = (msg.itemnum == nil) and 1 or msg.itemnum
            if nFeedCount <= 0 or nFeedCount > 99 then
                return false
            end
            local nNeedMoney = nArmourBaseConfig.feedmoney * nFeedCount
            local nEnoughtItem = true
            if ObjHuman.getYinliang(human) < nNeedMoney then
                nEnoughtItem = false
                msgErr.msg = "银两不足"
                Msg.send(msgErr, human.fd)
            end

            if BagLogic.getItemCount(human, nNeedItemID) < nArmourBaseConfig.feeditemnum * nFeedCount then
                nEnoughtItem = false
                msgErr.msg = "道具不足"
                Msg.send(msgErr, human.fd)
            end

            if nEnoughtItem == true then
                local len = #nArmourBaseConfig.feedAttr
                if len > 8 then
                    len = 8
                end

                local nRealFeedCount = 0
                local nAttrAdd = nil
                local nTotalAdd = {}
                for k = 1, nFeedCount do
                    nAttrAdd = ArmourLogicFL.randFeed(human, nArmourID, nArmourBaseConfig, nArmourDBData, len)
                    if not nAttrAdd then
                        msgErr.msg = Lang.ARMOUR_FEED_FULL
                        Msg.send(msgErr, human.fd)
                        break
                    end

                    local result = ArmourLogicFL.armourFeed(human, nArmourID, nArmourBaseConfig, nArmourDBData, nAttrAdd)

                    if result then
                        nRealFeedCount = nRealFeedCount + 1
                        for kk,vv in pairs(nAttrAdd) do
                            if nTotalAdd[kk] then
                                nTotalAdd[kk] = nTotalAdd[kk] + vv
                            else
                                nTotalAdd[kk] = vv
                            end
                        end
                    else
                        break
                    end
                end

                if nRealFeedCount > 0 then
                    ObjHuman.decYinliang(human, nArmourBaseConfig.feedmoney * nRealFeedCount, "armourfeed")
                    BagLogic.delItemsById(human, nNeedItemID, nArmourBaseConfig.feeditemnum * nRealFeedCount, "armourfeed")

                    ArmourLogicFL.updateArmour(human, nArmourID)
                    ObjHuman.doCalc(human)
                    ArmourLogicFL.send2ClientAllAttrUpdate(human)

                    sendArmourFeedData(human, nArmourID, nArmourBaseConfig, nTotalAdd)
                    msgErr.msg = Lang.ARMOUR_FEED_OK
                    Msg.send(msgErr, human.fd)
                    return true
                end
            end

            return
        end
    else
        local nStarConfigData = nArmourBaseConfig.starupdata[nStar + fromItemStar]
        if nStarConfigData then
            local result = ArmourLogicFL.armourStarUp(human, nArmourID, fromItemStar, nArmourDBData)
            if result then
                return true
            end
        end
    end
    return false
end

-- 战甲培养查询
function CG_ARMOUR_FEED_QUERY(human, msg)
    local nArmourID = msg.id
    if not ArmourLogicFL.armourValid(nArmourID) then
        return
    end

    local nArmourBaseConfig = ArmourBaseConfig[nArmourID]
    if nArmourBaseConfig then
        sendArmourFeedData(human, nArmourID, nArmourBaseConfig)
    end
end

function sendArmourAllAttr(human, allAttrUpdate)
    if allAttrUpdate then
        local nSendMsg = Msg.gc.GC_ARMOUR_ALLATTR
        nSendMsg.allAttr[0] = 0
        for k, v in pairs(allAttrUpdate) do
            nSendMsg.allAttr[0] = nSendMsg.allAttr[0] + 1
            local nAllAttrData = nSendMsg.allAttr[nSendMsg.allAttr[0]]
            nAllAttrData.key = k
            nAllAttrData.value = v
        end
        nSendMsg.allPower = RoleAttr.calPowerProto(nSendMsg.allAttr)
        Msg.send(nSendMsg, human.fd)
    end
end

--培养数据查询
function sendArmourFeedData(human, id, armourbaseconfig, attradd)
    local nArmourDBData = ArmourLogicFL.getArmourDBData(id, human)
    if not nArmourDBData then
        return
    end

    local nSendMsg = Msg.gc.GC_ARMOUR_FEED_QUERY
    nSendMsg.id = id
    local len = #armourbaseconfig.feedAttr
    if len > 8 then
        len = 8
    end
    for i = len + 1, 8 do
        nArmourDBData.feedAttr[i-1] = 0
    end
    local full =  ArmourLogicFL.isFeedFull(human, id, armourbaseconfig, nArmourDBData)
    for i = 1, len do
        nSendMsg.feedAttr[i].key = armourbaseconfig.feedAttr[i][1]
        nSendMsg.feedAttr[i].value = attradd and attradd[armourbaseconfig.feedAttr[i][1]] and nArmourDBData.feedAttr[i-1]-attradd[armourbaseconfig.feedAttr[i][1]] or nArmourDBData.feedAttr[i-1]
        if full or nArmourDBData.feedAttr[i-1] >= armourbaseconfig.feedAttr[i][2] then
            nSendMsg.feedAddVal[i] = -1
        else
            nSendMsg.feedAddVal[i] = attradd and attradd[armourbaseconfig.feedAttr[i][1]] or 0
        end
    end
    nSendMsg.feedAttr[0] = len
    nSendMsg.feedAddVal[0] = len
    Msg.send(nSendMsg, human.fd)
end


function warpArmourData(msgData, armourID, human, search)
    local nArmourBaseConfig = ArmourBaseConfig[armourID]
    local nArmourLvUpConfig = ArmourLogicFL.getLvUpConfig(armourID)
    if nArmourBaseConfig and nArmourLvUpConfig then
        msgData.id = armourID
        msgData.name = nArmourBaseConfig.name
        local nArmourDBData = ArmourLogicFL.getArmourDBData(armourID, human)
        local nArmourLv = nArmourDBData and nArmourDBData.lv or 0
        msgData.lv = nArmourLv
        msgData.state = nArmourDBData and nArmourDBData.state or ArmourDefine.ARMOUR_STATETYPE_UNHOLD
        msgData.star = nArmourDBData and nArmourDBData.star or 0
        msgData.feedstate = (msgData.star >= #nArmourBaseConfig.starupdata and not ArmourLogicFL.isFeedFull(human, armourID, nArmourBaseConfig, nArmourDBData)) and 1 or 0

        warpArmourCtl(msgData.ctllist, armourID, nArmourLv, search)

        warpArmourAttr(msgData.attrlist, armourID, nArmourLv)

        msgData.viewInfo[0] = 1
        warpArmourView(msgData.viewInfo, armourID, human)

        warpArmourStarCtl(msgData.starctllist, armourID, msgData.star, search)
        warpArmourStarAttr(msgData.starattrlist, armourID, msgData.star)

        warpArmourFeedCtl(msgData.feedctllist, armourID, search)
        warpArmourFeedAttr(msgData.feedattrlist, armourID, nArmourDBData)
    end
end

function warpArmourCtl(msgCtlList, armourID, armourLv, search)
    local nArmourBaseConfig = ArmourBaseConfig[armourID]
    local nArmourLvUpConfig = ArmourLogicFL.getLvUpConfig(armourID)
    local nItemList = nil
    if nArmourBaseConfig and nArmourLvUpConfig then
        local nCtlData = msgCtlList
        nCtlData.money = 0
        nCtlData.itemlist[0] = 0
        if not search then
            if armourLv == 0 then
                nItemList = nArmourBaseConfig.activeItem
            else
                local nArmourLvConfig = nArmourLvUpConfig[armourLv]
                if nArmourLvConfig then
                    nCtlData.money = nArmourLvConfig.updateMoney
                    nItemList = nArmourLvConfig.updateItem
                end
            end
            if nItemList then
                for k, v in ipairs(nItemList) do
                    nCtlData.itemlist[0] = nCtlData.itemlist[0] + 1
                    local nItemData = nCtlData.itemlist[nCtlData.itemlist[0]]
                    local grid = get_grid(v[1], v[2], 0, v[4] or 0)
                    Grid.makeItem(grid, nItemData)
                end
            end
        end
    end
end

function warpArmourAttr(msgAttrData, armourID, armourLv)
    local nArmourBaseConfig = ArmourBaseConfig[armourID]
    local nArmourLvUpConfig = ArmourLogicFL.getLvUpConfig(armourID)
    if nArmourBaseConfig and nArmourLvUpConfig then
        local nAttrData = msgAttrData
        nAttrData.curAttr[0] = 0
        nAttrData.curPower = 0
        nAttrData.nextAttr[0] = 0
        nAttrData.nextPower = 0
        local nCurAttr = nil
        local nNextAttr = nil
        if armourLv == 0 then
            nNextAttr = nArmourLvUpConfig[1] and nArmourLvUpConfig[1].addAttr or nil
        else
            nCurAttr = nArmourLvUpConfig[armourLv] and nArmourLvUpConfig[armourLv].addAttr or nil
            nNextAttr = nArmourLvUpConfig[armourLv + 1] and nArmourLvUpConfig[armourLv + 1].addAttr or nil
        end
        if nCurAttr then
            for k, v in ipairs(nCurAttr) do
                nAttrData.curAttr[0] = nAttrData.curAttr[0] + 1
                local nCurAttrData = nAttrData.curAttr[nAttrData.curAttr[0]]
                nCurAttrData.key = v[1]
                nCurAttrData.value = v[2]
            end
            nAttrData.curPower = RoleAttr.calPowerProto(nAttrData.curAttr)
        end
        if nNextAttr then
            for k, v in ipairs(nNextAttr) do
                nAttrData.nextAttr[0] = nAttrData.nextAttr[0] + 1
                local nNextAttr = nAttrData.nextAttr[nAttrData.nextAttr[0]]
                nNextAttr.key = v[1]
                nNextAttr.value = v[2]
            end
            nAttrData.nextPower = RoleAttr.calPowerProto(nAttrData.nextAttr)
        end
    end
end

function warpArmourView(msgViewData, armourID, human)
    Status.makeViewInfo(msgViewData, human.db.sex, Obj.getBodyInfo(human))
    msgViewData.head, msgViewData.body, msgViewData.pifeng, msgViewData.leftarm, msgViewData.rightarm = ArmourDefine.getViewInfo(armourID, human.db.sex)
end

function warpArmourStarCtl(msgStarCtlList, armourID, armourStar, search)
    local nArmourBaseConfig = ArmourBaseConfig[armourID]
    if nArmourBaseConfig then
        local nCtlData = msgStarCtlList
        nCtlData.money = 0
        nCtlData.itemlist[0] = 0
        if not search then
            local nArmourStarData = nArmourBaseConfig.starupdata[armourStar + 1]
            if nArmourStarData then
                nCtlData.money = nArmourStarData[2] or 0
                nCtlData.itemlist[0] = 1
                local nItemData = nCtlData.itemlist[nCtlData.itemlist[0]]
                local grid = get_grid(nArmourBaseConfig.starItem, nArmourStarData[1], 0, 0)
                Grid.makeItem(grid, nItemData)
            end
        end
    end
end

function warpArmourStarAttr(msgAttrData, armourID, armourStar)
    local nArmourBaseConfig = ArmourBaseConfig[armourID]
    if nArmourBaseConfig then
        local nAttrData = msgAttrData
        nAttrData.curAttr[0] = 0
        nAttrData.curPower = 0
        nAttrData.nextAttr[0] = 0
        nAttrData.nextPower = 0
        local nArmourStarAttrData = nArmourBaseConfig.starattrdata
        if nArmourStarAttrData then
            local nCurAttr = nil
            local nNextAttr = nil
            nCurAttr = nArmourStarAttrData[armourStar] or nil
            nNextAttr = nArmourStarAttrData[armourStar + 1] or nil

            if nCurAttr then
                for k, v in ipairs(nCurAttr) do
                    nAttrData.curAttr[0] = nAttrData.curAttr[0] + 1
                    local nCurAttrData = nAttrData.curAttr[nAttrData.curAttr[0]]
                    nCurAttrData.key = v[1]
                    nCurAttrData.value = v[2]
                end
                nAttrData.curPower = RoleAttr.calPowerProto(nAttrData.curAttr)
            end
            if nNextAttr then
                for k, v in ipairs(nNextAttr) do
                    nAttrData.nextAttr[0] = nAttrData.nextAttr[0] + 1
                    local nNextAttr = nAttrData.nextAttr[nAttrData.nextAttr[0]]
                    nNextAttr.key = v[1]
                    nNextAttr.value = v[2]
                end
                nAttrData.nextPower = RoleAttr.calPowerProto(nAttrData.nextAttr)
            end

        end
    end
end

function warpArmourFeedCtl(msgStarCtlList, armourID, search)
    local nArmourBaseConfig = ArmourBaseConfig[armourID]
    if nArmourBaseConfig then
        local nCtlData = msgStarCtlList
        nCtlData.money = 0
        nCtlData.itemlist[0] = 0
        if not search then
            nCtlData.money = nArmourBaseConfig.feedmoney
            nCtlData.itemlist[0] = 1
            local nItemData = nCtlData.itemlist[nCtlData.itemlist[0]]
            local grid = get_grid(nArmourBaseConfig.starItem, nArmourBaseConfig.feeditemnum, 0, 0)
            Grid.makeItem(grid, nItemData)
        end
    end
end

function warpArmourFeedAttr(msgAttrData, armourID, nArmourDBData)
    local nArmourBaseConfig = ArmourBaseConfig[armourID]
    if nArmourBaseConfig then
        local nAttrData = msgAttrData
        nAttrData.curAttr[0] = 0
        nAttrData.curPower = 0
        nAttrData.nextAttr[0] = 0
        nAttrData.nextPower = 0

        if nArmourDBData then
            local nLen = #nArmourBaseConfig.feedAttr
            if nLen > 8 then
                nLen = 8
            end
            for i = nLen + 1, 8 do
                nArmourDBData.feedAttr[i-1] = 0
            end

            local full =  ArmourLogicFL.isFeedFull(human, armourID, nArmourBaseConfig, nArmourDBData)
            for i = 1, nLen do
                nAttrData.curAttr[i].key = nArmourBaseConfig.feedAttr[i][1]
                nAttrData.curAttr[i].value = nArmourDBData.feedAttr[i-1]
            end
            nAttrData.curAttr[0] = nLen
        end
    end
end

function warpSearch(msgData, human)
    msgData.armourlist[0] = 0
    msgData.allAttr[0] = 0
    msgData.allPower = 0

    for k, v in pairs(ArmourBaseConfig) do
        msgData.armourlist[0] = msgData.armourlist[0] + 1
        local nArmourData = msgData.armourlist[msgData.armourlist[0]]
        warpArmourData(nArmourData, k, human, true)
    end

    local nAllAttr = ArmourLogicFL.calcAllAttr(human)
    if nAllAttr then
        for k, v in pairs(nAllAttr) do
            msgData.allAttr[0] = msgData.allAttr[0] + 1
            local nAllAttrData = msgData.allAttr[msgData.allAttr[0]]
            nAllAttrData.key = k
            nAllAttrData.value = v
        end
        msgData.allPower = RoleAttr.calPowerProto(msgData.allAttr)
    end
end
